g_serie_color_array = [
	'red', 'blue', 'limegreen', 'black', 'lightsalmon', 'royalblue', 'mediumvioletred', 'seagreen',
	'aqua', 'blueviolet', 'brown', 'cadetblue', 'darkblue', 'darkcyan', 'darkorchid', 'darkred',
	'dodgerblue', 'firebrick', 'forestgreen', 'hotpink', 'indigo', 'darkorange', 'maroon', 'orangered',
	'purple', 'saddlebrown', 'violetred', 'olive', 'midnightblue', 'peru', 'springgreen', 'yellow'
]

function RTChart(container_id, is_mp)
{
	// constant properties
	this.CHART_Y_AXIS_DEC_PLACES = 1

	this.ctx = undefined
	this.canv = undefined
	this.width = 0
	this.height = 0
	this.org_x = 0
	this.org_y = 0
	this.margin_x = 0
	this.margin_y = 0
	this.grid_num_vert = 10
	this.grid_num_horz = 5
	this.x_scale_min = 0
	this.x_scale_max = 0
	this.y_scale_min = 0
	this.y_scale_max = 0
	this.series = []
	this.s_color = []
	this.name_array = []
	this.s_info = []

	this.add_serie = function(s, na) {
		this.name_array = na
		for (var i = 0; i < na.length; i++) {
			this.s_info[i] = {}
			this.s_info[i]['title'] = na[i]
			this.s_info[i]['visible'] = true
		}
		this.series = s.slice()
		// remove min, max and avr rows
		this.series.shift()
		this.series.shift()
		this.series.shift()
		__rt_chart_redraw(this)
	}

	this.reset = function() {
		this.x_scale_min = 0
		this.x_scale_max = 0
		this.y_scale_min = 0
		this.y_scale_max = 0
		this.series = {}
		this.name_array = []
		this.s_info = []
		this.mp_data_array = []
		this.pm_val_array = []
		this.mp_cur_var_index = 0
		}

	// for multi-plotting
	this.is_mp = is_mp
	this.mp_data_array = []
	this.pm_val_array = []
	this.mp_cur_var_index = 0

	this.set_current_var = function(idx) {
		this.mp_cur_var_index = idx
	}

	this.show_wpm_serie = function(index, is_visible) {
		if (index == -1) {
			for (var i = 0; i < this.mp_data_array.length; i++) {
				this.mp_data_array[i].visible = is_visible
			}
		} else {
			var mp_obj = this.mp_data_array[index]
			mp_obj.visible = is_visible
		}
		this.redraw()
	}

	this.add_wfr_pm_data = function(wafer_id, pm_name, org_data) {
		var data = org_data.rows.slice()
		var mp_obj = {}
		mp_obj['data'] = data
		mp_obj['wid'] = wafer_id
		mp_obj['pm'] = pm_name
		mp_obj['visible'] = true
		
		// remove avr, min, max
		data.shift()
		data.shift()
		data.shift()
		var time_base = parseInt(data[0].time)
		for (var i = 0; i < data.length; i++) {
			var nt = parseInt(data[i].time) - time_base
		//	console.log(nt)
			data[i].time = nt
		}
		this.mp_data_array.push(mp_obj)
		console.log(this.mp_data_array)
	}

	this.redraw = function(cursor_location) {
		__rt_chart_redraw(this, cursor_location)
	}
	
	__rt_chart_init(this, container_id)
	__rt_chart_draw_base(this)
}

function __rt_chart_init(chart, container_id)
{
	var container = document.getElementById(container_id)
	var canv = document.createElement("canvas")
	canv.setAttribute('style', 'border:1px solid #000;')
	canv.width = container.clientWidth
	canv.height = container.clientHeight
	container.appendChild(canv)
	chart.canv = canv

	chart.ctx = canv.getContext("2d")
	if (chart.is_mp) {
		chart.width = canv.width
	} else {
		chart.width = canv.width * 0.8
	}
	chart.height = canv.height
	chart.margin_x = (chart.width*0.05) + 10
	chart.margin_y = (chart.height*0.1)
	chart.org_x = chart.margin_x
	chart.org_y = chart.height - chart.margin_y

	chart.s_color = g_serie_color_array
//	console.log(chart)

	__rt_chart_init_event(canv, chart)
}

function getLocation(canvas, x, y)
{
	var bbox = canvas.getBoundingClientRect();
	return {
		x: (x - bbox.left) * (canvas.width / bbox.width),
		y: (y - bbox.top) * (canvas.height / bbox.height)
	};
}

function __rt_chart_init_event(canv, chart)
{
	if (chart.is_mp) {
		canv.onmousemove = function(e)
		{
			var loc = getLocation(canv, e.clientX, e.clientY)
		
			if (loc.x >= chart.margin_x && loc.x <= (chart.width - chart.margin_x) &&
				loc.y >= chart.margin_y && loc.y <= (chart.height - chart.margin_y))
			{
				chart.redraw(loc)
			}
		}	
		return
	}

	canv.onmousemove = function(e)
	{
		if (chart.series.length == undefined || chart.series.length == 0) {
			return
		}
		var loc = getLocation(canv, e.clientX, e.clientY)
		
		if (loc.x >= chart.margin_x && loc.x <= (chart.width - chart.margin_x) &&
			loc.y >= chart.margin_y && loc.y <= (chart.height - chart.margin_y))
		{
			this.style.cursor = 'crosshair'
			__rt_chart_draw_base(chart)
			__rt_chart_draw_all_series(chart)
			__rt_chart_draw_cursor_line(chart, loc.x)
			var box_x = loc.x
			var box_y = loc.y
			if (((chart.width - chart.margin_x) - box_x) < 200) {
				box_x -= 208
			}
			__rt_chart_draw_cursor_info(chart, loc.x, box_x, box_y, false)
		
			return
		}

		for (var i = 0; i < chart.name_array.length; i++) {
			var left = chart.width + 2
			var top = 30 + 20 * i - 10
			var width = 120
			var height = 16
			if (loc.x >= left && loc.x <= (left + width) &&
				loc.y >= top && loc.y <= (top + height))
			{
				this.style.cursor = 'pointer'
				return
			}
		}

		this.style.cursor = 'auto'
	}

	canv.onmousedown = function(e)
	{
		var loc = getLocation(canv, e.clientX, e.clientY)
		
		for (var i = 0; i < chart.name_array.length; i++) {
			var left = chart.width + 2
			var top = 30 + 20 * i - 10
			var width = 120
			var height = 16
			if (loc.x >= left && loc.x <= (left + width) &&
			loc.y >= top && loc.y <= (top + height))
			{
				__rt_chart_showhide_serie(chart, i)
				__rt_chart_redraw(chart, loc)
				return
			}
		}
	}
}

function __rt_chart_showhide_serie(chart, index)
{
	chart.s_info[index]['visible'] = !chart.s_info[index]['visible']
//	console.log(index, ':', chart.s_info[index]['visible'])
}

function __rt_chart_redraw(chart, cursor_location)
{
	__rt_chart_draw_base(chart)
	if (chart.is_mp) {
		__rt_chart_draw_all_series_mp(chart, cursor_location)
	} else {
		__rt_chart_draw_all_series(chart)
		__rt_chart_draw_legend(chart)	
	}
}

function __rt_chart_draw_base(chart)
{
	chart.ctx.fillStyle = "#f6f6f6"
	chart.ctx.fillRect(0, 0, chart.width, chart.height)

	// draw x-y axis lines
	chart.ctx.strokeStyle = '#000000'
	chart.ctx.lineWidth = 1
	chart.ctx.beginPath()
	chart.ctx.moveTo(chart.org_x, chart.org_y)
	chart.ctx.lineTo(chart.width - chart.margin_x, chart.org_y)
	chart.ctx.stroke()
	chart.ctx.moveTo(chart.org_x, chart.org_y)
	chart.ctx.lineTo(chart.org_x, chart.margin_y)
	chart.ctx.stroke()

	// draw vertical grid lines
	chart.ctx.strokeStyle = '#cccccc'
	chart.ctx.lineWidth = 1
	for (var i = 1; i <= chart.grid_num_vert; i++) {
		chart.ctx.beginPath()
		var ident = (chart.width - chart.margin_x*2)/chart.grid_num_vert
		chart.ctx.moveTo(chart.org_x + ident*i, chart.org_y)
		chart.ctx.lineTo(chart.org_x + ident*i, chart.margin_y)
		chart.ctx.stroke()
	}

	// horizontal
	for (var i = 1; i <= chart.grid_num_horz; i++) {
		chart.ctx.beginPath()
		var ident = (chart.height - chart.margin_y*2)/chart.grid_num_horz
		chart.ctx.moveTo(chart.org_x, chart.org_y - ident*i)
		chart.ctx.lineTo(chart.width - chart.margin_x, chart.org_y - ident*i)
		chart.ctx.stroke()
	}
}

function __rt_chart_draw_legend(chart)
{
	chart.ctx.fillStyle = '#ffffff'
	chart.ctx.fillRect(chart.width, 0, 130, chart.height)
	for (var i = 0; i < chart.name_array.length; i++) {
		chart.ctx.fillStyle = chart.s_color[i]
		chart.ctx.fillRect(chart.width + 10, 30 + 20 * i - 10, 16, 16)
	
		chart.ctx.fillStyle = chart.s_info[i]['visible'] ? '#cccccc' : '#ffffff'
		chart.ctx.fillRect(chart.width + 28, 30 + 20 * i - 10, 100, 16)
		chart.ctx.font = "10px Arial"
		chart.ctx.fillStyle = '#000000' // chart.s_color[i]
		chart.ctx.fillText(chart.s_info[i]['title'], chart.width + 28, 30 + 20 * i, 100, 16)
	}
}

function __rt_chart_x_to_time(chart, x)
{
	var tspan = chart.x_scale_max - chart.x_scale_min
	var tval = tspan * (x - chart.margin_x) / (chart.width - chart.margin_x*2) + chart.x_scale_min
	return tval
}

function __rt_chart_get_value(chart, index, tval)
{
	var left_i = 0
	var right_i = chart.series.length
	var ci = 0
//	debugger
	while (left_i < right_i) {
		ci = parseInt((left_i + right_i)/2)
		var ct = chart.series[ci].time
		if (tval < ct) {
			right_i = ci - 1
		} else if (tval > ct) {
			left_i = ci + 1
		} else {
			break
		}
	}
	return parseFloat(chart.series[ci].v[index]).toFixed(3)
}

function __rt_chart_get_value_mp(chart, index, tval)
{
	var wpm_ob = chart.mp_data_array[index]
	var cur_idx = chart.mp_cur_var_index + 1
	var fn = (cur_idx > 9) ? ('data' + cur_idx) : ('data0' + cur_idx)

	var left_i = 0
	var right_i = wpm_ob.data.length
	var ci = 0
	while (left_i < right_i) {
		ci = parseInt((left_i + right_i)/2)
		var ct = wpm_ob.data[ci].time
		if (tval < ct) {
			right_i = ci - 1
		} else if (tval > ct) {
			left_i = ci + 1
		} else {
			break
		}
	}
	return parseFloat(wpm_ob.data[ci][fn]).toFixed(3)
}

function __rt_chart_draw_cursor_info(chart, cursor_x, x, y, is_mp)
{
	var BOX_WIDTH = 200
	var ROW_HEIGHT = 16
	// draw time
	chart.ctx.fillStyle = '#ffff00'
	chart.ctx.fillRect(x + 4, y + 4, BOX_WIDTH, ROW_HEIGHT)

	var tval = __rt_chart_x_to_time(chart, cursor_x)
	var ts = new Date(tval)
	var t_str = 'Time: '
	if (is_mp) {
		t_str += datetime_format(ts, 'ss.SSS')
	} else {
		t_str += datetime_format(ts, 'yyyy-MM-dd hh:mm:ss.SSS')
	}

	chart.ctx.font = "10px Arial"
	chart.ctx.fillStyle = '#000000'
	chart.ctx.fillText(t_str, x + 4, y + 14, BOX_WIDTH, ROW_HEIGHT)

	// draw value
	if (is_mp) {
		var wpm_array = chart.mp_data_array
		var ser_count = wpm_array.length
		var cur_idx = chart.mp_cur_var_index + 1
		var fn = (cur_idx > 9) ? ('data' + cur_idx) : ('data0' + cur_idx)
		var disp_count = 0
		for (var i = 0; i < ser_count; i++) {
			if (wpm_array[i].visible) {
				disp_count++
			}
		}
		chart.ctx.fillStyle = '#ccccff'
		chart.ctx.fillRect(x + 4, y + 20, BOX_WIDTH, ROW_HEIGHT * disp_count)
		var row_count = 0
		for (var i = 0; i < ser_count; i++) {
			if (!wpm_array[i].visible) {
				continue
			}
			var wpm_ob = wpm_array[i]
			chart.ctx.fillStyle = chart.s_color[i]
			chart.ctx.fillRect(x + 4, y + 20 + ROW_HEIGHT * row_count, ROW_HEIGHT, ROW_HEIGHT)
			chart.ctx.font = "10px Arial"
			chart.ctx.fillStyle = '#000000'
			var name = wpm_ob.wid + '/' + wpm_ob.pm
			chart.ctx.fillText(name, x + 22, y + 33 + ROW_HEIGHT * row_count, BOX_WIDTH, ROW_HEIGHT)
			// item value
			var data = __rt_chart_get_value_mp(chart, i, tval)
			chart.ctx.fillText(data, x + 145, y + 33 + ROW_HEIGHT * row_count, BOX_WIDTH, ROW_HEIGHT)
			row_count++
		}
	} else {
		var disp_count = 0
		for (var i = 0; i < chart.name_array.length; i++) {
			if (chart.s_info[i]['visible']) {
				disp_count++
			}
		}
		chart.ctx.fillStyle = '#ccccff'
		chart.ctx.fillRect(x + 4, y + 20, BOX_WIDTH, ROW_HEIGHT * disp_count)
	
		var tval = __rt_chart_x_to_time(chart, cursor_x)
		var row_count = 0
		for (var i = 0; i < chart.name_array.length; i++) {
			if (chart.s_info[i]['visible']) {
				// item name
				chart.ctx.fillStyle = chart.s_color[i]
				chart.ctx.fillRect(x + 4, y + 20 + ROW_HEIGHT * row_count, ROW_HEIGHT, ROW_HEIGHT)
				chart.ctx.font = "10px Arial"
				chart.ctx.fillStyle = '#000000'
				chart.ctx.fillText(chart.s_info[i]['title'], x + 22, y + 33 + ROW_HEIGHT * row_count, BOX_WIDTH, ROW_HEIGHT)
				// item value
				var data = __rt_chart_get_value(chart, i, tval)
				chart.ctx.fillText(data, x + 145, y + 33 + ROW_HEIGHT * row_count, BOX_WIDTH, ROW_HEIGHT)
				row_count++
			}
		}
	}
}

function __rt_chart_draw_cursor_line(chart, x)
{
	chart.ctx.strokeStyle = '#aaaaaa'
	chart.ctx.lineWidth = 1
	chart.ctx.beginPath()
	chart.ctx.moveTo(x, chart.margin_y)
	chart.ctx.lineTo(x, chart.height - chart.margin_y)
	chart.ctx.stroke()
}

// for multi-variables-plotting
function __rt_chart_draw_all_series_mp(chart, cursor_loc)
{
	var wpm_array = chart.mp_data_array

	// draw time scale value, get max time first
	var max_time = 0
	for (var i = 0; i < wpm_array.length; i++) {
		var mp_ob = wpm_array[i]
		var pt_count = mp_ob.data.length
		var __t = mp_ob.data[pt_count - 1].time
		max_time = Math.max(max_time, __t)
	}
	chart.x_scale_min = 0
	chart.x_scale_max = max_time
	var tspan = chart.x_scale_max - chart.x_scale_min
	var ident = (chart.width - chart.margin_x*2)/chart.grid_num_vert
	var t_idt = tspan / chart.grid_num_vert
	for (var i = 0; i <= chart.grid_num_vert; i++) {
		var ts = new Date(t_idt * i)
		var __t_str = datetime_format(ts, 'ss.SSS')
		chart.ctx.font = "10px Arial"
		chart.ctx.fillStyle = "#222222"
		chart.ctx.fillText(__t_str,
			chart.org_x + ident*i - 15, chart.org_y + 18, 100, 16)
	}

	// draw Y axis scale values
	var y_min = 999999 //Number.MAX_VALUE
	var y_max = -999999 // Number.MIN_VALUE

	var ser_count = wpm_array.length
	var cur_idx = chart.mp_cur_var_index + 1
	var fn = (cur_idx > 9) ? ('data' + cur_idx) : ('data0' + cur_idx)
	var all_hide = true
	for (var i = 0; i < ser_count; i++) {
		if (wpm_array[i].visible) {
			all_hide = false
			var pt_count = wpm_array[i].data.length
			for (var k = 0; k < pt_count; k++) {
				y_min = Math.min(y_min, wpm_array[i].data[k][fn])
				y_max = Math.max(y_max, wpm_array[i].data[k][fn])
			}
		}
	}
	console.log(fn + ": " + y_min + ", " + y_max)
	if (all_hide) {
		return
	}

	var idt_y = (y_max - y_min)*1.2 / chart.grid_num_horz
	var y_scale_min = y_min - (y_max - y_min) * 0.1
	for (var i = 0; i <= chart.grid_num_horz; i++) {
		var __v = y_scale_min + idt_y*i
		var __idt = (chart.height - chart.margin_y*2)/chart.grid_num_horz

		chart.ctx.font = "11px Arial"
		chart.ctx.fillStyle = "#222222"
		chart.ctx.fillText(
			parseFloat(__v).toFixed(chart.CHART_Y_AXIS_DEC_PLACES),
			chart.org_x - 35, chart.org_y - __idt*i, 100, 16)
	}
	chart.y_scale_min = y_scale_min
	chart.y_scale_max = y_scale_min + idt_y*chart.grid_num_horz

	// draw lines
	for (var i = 0; i < ser_count; i++) {
		if (!wpm_array[i].visible) {
			continue
		}

		chart.ctx.beginPath()
		chart.ctx.strokeStyle = chart.s_color[i]
		chart.ctx.lineWidth = 1
		var pt_count = wpm_array[i].data.length
		var prev_x, prev_y
		for (var k = 0; k < pt_count; k++) {
			var v = wpm_array[i].data[k][fn]
			var t = wpm_array[i].data[k].time
			// transform t-val to x-y
			var xx = (t - chart.x_scale_min)/(chart.x_scale_max-chart.x_scale_min)*(chart.width - chart.margin_x*2) + chart.org_x
			var yy = chart.org_y - (v - chart.y_scale_min)/(chart.y_scale_max-chart.y_scale_min)*(chart.height - chart.margin_y*2)
			if (k > 0) {
				chart.ctx.moveTo(prev_x, prev_y)
				chart.ctx.lineTo(xx, yy)
			}
			prev_x = xx
			prev_y = yy
		}
		chart.ctx.stroke()
	}

	// draw timeline values
	if (cursor_loc != null) {
		chart.canv.style.cursor = 'crosshair'
		__rt_chart_draw_cursor_line(chart, cursor_loc.x)
		var box_x = cursor_loc.x
		var box_y = cursor_loc.y
		if (((chart.width - chart.margin_x) - box_x) < 200) {
			box_x -= 208
		}
		__rt_chart_draw_cursor_info(chart, cursor_loc.x, box_x, box_y, true)
}
}

function __rt_chart_draw_all_series(chart)
{
	var data = chart.series
//	debugger
	chart.x_scale_min = data[0].time
	chart.x_scale_max = data[data.length-1].time
	var tspan = chart.x_scale_max - chart.x_scale_min
	// draw time scale value
	var ident = (chart.width - chart.margin_x*2)/chart.grid_num_vert
	var t_idt = tspan / chart.grid_num_vert
	for (var i = 0; i <= chart.grid_num_vert; i++) {
		var ts = new Date(data[0].time + t_idt*i)
		var __t_str = datetime_format(ts, 'ss.SSS')
		chart.ctx.font = "10px Arial"
		chart.ctx.fillStyle = "#222222"
		chart.ctx.fillText(__t_str,
			chart.org_x + ident*i - 15, chart.org_y + 18, 100, 16)
	}

	var s_count = chart.s_info.length

	for (var i = 0; i < data.length; i++) {
		data[i]['v'] = []
		for (var k = 1; k <= s_count; k++) {
		//	if (chart.s_info[k-1]['visible']) {
				var fn = (k > 9) ? ('data' + k) : ('data0' + k)
				data[i]['v'].push(data[i][fn])
		//	}
		}
	}
//	debugger

	// y scale
	var y_min = 0
	var y_max = 0
	for (var k = 0; k < s_count; k++) {
		if (chart.s_info[k]['visible']) {
			y_min = data[0].v[k]
			y_max = data[0].v[k]
		}
	}
//	console.log('[1]', y_min, ', ', y_max)

	for (var i = 0; i < data.length; i++) {
		for (var k = 0; k < s_count; k++) {
			if (chart.s_info[k]['visible']) {
				if (y_min > data[i].v[k]) y_min = data[i].v[k]
				if (y_max < data[i].v[k]) y_max = data[i].v[k]
			}
		}
	}
	var idt_y = (y_max - y_min)*1.2 / chart.grid_num_horz
	var y_scale_min = y_min - (y_max - y_min) * 0.1
	for (var i = 0; i <= chart.grid_num_horz; i++) {
		var __v = y_scale_min + idt_y*i
		var __idt = (chart.height - chart.margin_y*2)/chart.grid_num_horz

		chart.ctx.font = "11px Arial"
		chart.ctx.fillStyle = "#222222"
		chart.ctx.fillText(
			parseFloat(__v).toFixed(chart.CHART_Y_AXIS_DEC_PLACES),
			chart.org_x - 45, chart.org_y - __idt*i, 100, 16)
	}
	chart.y_scale_min = y_scale_min
	chart.y_scale_max = y_scale_min + idt_y*chart.grid_num_horz
//	console.log(chart.y_scale_min, ', ', chart.y_scale_max)

	// draw lines
	for (var k = 0; k < s_count; k++) {
		if (!chart.s_info[k]['visible']) {
			continue
		}
		var xy_data = []
		for (var i = 0; i < data.length; i++) {
			var t = data[i].time
			var v = data[i].v[k]
			// transform t-val to x-y
			var xx = (t - chart.x_scale_min)/(chart.x_scale_max-chart.x_scale_min)*(chart.width - chart.margin_x*2) + chart.org_x
			var yy = chart.org_y - (v - chart.y_scale_min)/(chart.y_scale_max-chart.y_scale_min)*(chart.height - chart.margin_y*2)
			xy_data.push({
				'x':xx, 'y':yy
			})
		}
	//	console.log(xy_data)
		chart.ctx.beginPath()
		chart.ctx.strokeStyle = chart.s_color[k]
		chart.ctx.lineWidth = 1
		for (var i = 0; i < xy_data.length - 1; i++) {
			chart.ctx.moveTo(xy_data[i].x, xy_data[i].y)
			chart.ctx.lineTo(xy_data[i+1].x, xy_data[i+1].y)
		}
		chart.ctx.stroke()
	}
}
